
package org.sopt.dev.ImgKnight.frontier.Filter;

import java.io.IOException;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;

import org.apache.log4j.Logger;
import org.apache.commons.collections.map.LRUMap;

import org.sopt.dev.ImgKnight.frontier.Frontier;

import com.maxmind.geoip.Country;
import com.maxmind.geoip.LookupService;

public class GeoLocationFilter {
	
	private Frontier frontier = null;
	
	private Logger serviceLogger = null;
	
	private Logger exceptionLogger = null;
	
	private LookupService lookup = null;
	
	private LRUMap geoLocationCache = null;
	
	public GeoLocationFilter(int geoLocationCacheSize) {
		frontier = Frontier.getInstance();
		geoLocationCache = new LRUMap(geoLocationCacheSize);
		serviceLogger = Logger.getLogger("frontier.service");
		exceptionLogger = Logger.getLogger("frontier.exception");	
		try {
			lookup = new LookupService(frontier.getFrontierConfig().GeoLocationDataBase,
					LookupService.GEOIP_MEMORY_CACHE);
		} catch (IOException e) {
			exceptionLogger.error("Unexpected exception: "+e);
		}
	}
	
	public String getGeoCountryCode(URL url) {
		String countryCode = null;
		Country country = null;
		synchronized (geoLocationCache) {
			country = (Country)geoLocationCache.get(url.getHost());
		}
		if( country != null ) {
			countryCode = country.getCode();
		}
		else {
			try {
				InetAddress inetAddress = InetAddress.getByName(url.getHost());
				country = lookup.getCountry(inetAddress.getHostAddress());
				if( country != null ) {
					synchronized (geoLocationCache) {
						geoLocationCache.put(url.getHost(), country);
					}
				}
				countryCode = country.getCode();
			} catch (UnknownHostException e) { }
		}
		return countryCode;
	}
	
	public String getGeoCountryName(URL url) {
		String countryName = null;
		Country country = null;
		synchronized (geoLocationCache) {
			country = (Country)geoLocationCache.get(url.getHost());
		}
		if( country != null ) {
			countryName = country.getName();
		}
		else {
			try {
				InetAddress inetAddress = InetAddress.getByName(url.getHost());
				country = lookup.getCountry(inetAddress.getHostAddress());
				if( country != null ) {
					synchronized (geoLocationCache) {
						geoLocationCache.put(url.getHost(), country);
					}
				}
				countryName = country.getName();
			} catch (UnknownHostException e) { }
		}
		return countryName;
	}
	
	public boolean validate(URL url) {
		String countryCode = getGeoCountryCode(url);
		if( countryCode == null )
			return false;	
		if( frontier.getFrontierConfig().containsAllowCountryCode(countryCode) ) {
			serviceLogger.debug("Allow: "+countryCode+": "+url+": "+countryCode);
			return true;
		}
		if( frontier.getFrontierConfig().containsDenyCountryCode(countryCode) ) {
			serviceLogger.debug("Deny"+countryCode+": "+url+": "+countryCode);
			return false;
		}
		return (frontier.getFrontierConfig().GeoLocationFilterDefaultAction == 1 ) ? true : false;
	}
	
}
